
#include "main.hpp"
#include "esp_timer.h"
#include "guiDemo/gui_Demo.h"

#define TAG "demo"
#define LV_TICK_PERIOD_MS 2

static SemaphoreHandle_t xGuiSemaphore;

extern void uuid_Times(int t);

/* Creates a semaphore to handle concurrent call to lvgl stuff
 * If you wish to call *any* lvgl function from other threads/tasks
 * you should lock on the very same semaphore! */
/*********************** GUI_SHOW_CODE_START***********************/

typedef void(*CURR_WIN_RUN)(void);
typedef void(*CURR_WIN_CREATE)(lv_obj_t * parent);
#define CURR_WIN_NUM  5

CURR_WIN_CREATE currWinCreate[CURR_WIN_NUM]={
    gui_main_win_create,
    gui_fault_win_create,
    gui_wifi_win_create,
    gui_player_win_create,
    gui_msg_win_create,
};
CURR_WIN_RUN currWinRun[CURR_WIN_NUM]={
    gui_main_win_run,
    gui_fault_win_run,
    gui_wifi_win_run,
    gui_player_win_run,
    gui_msg_win_run,
};
//研究滑动切换
lv_scr_load_anim_t load_right_left = LV_SCR_LOAD_ANIM_MOVE_LEFT;
unsigned short imgrRunCnt = 0,currWin = 2;
bool isWinSwitch = false,isFirstWin = 0;
static void drag_event_handler(lv_event_t * e)
{
    static   lv_coord_t last_x = 0,isValidX = 0;
    bool isSwitch = 0;
    lv_indev_t * indev = lv_indev_get_act();
    if(indev == NULL)  return;
    lv_point_t vect;
    lv_indev_get_vect(indev, &vect);

   lv_event_code_t code = lv_event_get_code(e);
   if(code == LV_EVENT_PRESSING){
        last_x = vect.x;
        isValidX = 1;
   }
   else if(code == LV_EVENT_LONG_PRESSED){
        if(isValidX){
            isValidX = 0;
            if( vect.x > last_x + 1){
                isSwitch = 1;
                load_right_left = LV_SCR_LOAD_ANIM_MOVE_RIGHT;
            }
            else if( vect.x + 1 <= last_x ){
                isSwitch = 1;
                load_right_left = LV_SCR_LOAD_ANIM_MOVE_LEFT;
            }
        }
   }

   if(1){
        if(++currWin >= CURR_WIN_NUM){
            currWin = 0;
        }
        isFirstWin = 0;
   }

}

extern "C" void lv_tick_task(void *arg)
{
    (void) arg;
    lv_tick_inc(LV_TICK_PERIOD_MS);
    //ESP_LOGI(TAG, "Periodic timer called");
}
/* Creates a semaphore to handle concurrent call to lvgl stuff
 * If you wish to call *any* lvgl function from other threads/tasks
 * you should lock on the very same semaphore! */

extern "C" void guiTask(void *pvParameter)
{
    (void) pvParameter;
    xGuiSemaphore = xSemaphoreCreateMutex();


    lv_init();

    /* Initialize SPI or I2C bus used by the drivers */
    lvgl_driver_init();

    lv_color_t* buf1 = (lv_color_t*)heap_caps_malloc(DISP_BUF_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA);
    assert(buf1 != NULL);

    lv_color_t* buf2 = (lv_color_t*)heap_caps_malloc(DISP_BUF_SIZE * sizeof(lv_color_t), MALLOC_CAP_DMA);
    assert(buf2 != NULL);

    static lv_disp_draw_buf_t disp_buf;
    uint32_t size_in_px = DISP_BUF_SIZE;
    lv_disp_draw_buf_init(&disp_buf, buf1, buf2, size_in_px);

    lv_disp_drv_t disp_drv;
    lv_disp_drv_init(&disp_drv);
    disp_drv.hor_res=LV_HOR_RES_MAX;
    disp_drv.ver_res=LV_VER_RES_MAX;
    disp_drv.flush_cb = disp_driver_flush;
    disp_drv.draw_buf = &disp_buf;
    lv_disp_drv_register(&disp_drv);

    /* Register an input device when enabled on the menuconfig */
#if CONFIG_LV_TOUCH_CONTROLLER != TOUCH_CONTROLLER_NONE
    lv_indev_drv_t indev_drv;
    lv_indev_drv_init(&indev_drv);
    indev_drv.read_cb   = touch_driver_read;
    indev_drv.type      = LV_INDEV_TYPE_POINTER;
    lv_indev_drv_register(&indev_drv);
#endif

    /* Create and start a periodic timer interrupt to call lv_tick_inc */
    const esp_timer_create_args_t periodic_timer_args = {
        .callback = &lv_tick_task,
        .name = "periodic_gui"
    };


    esp_timer_handle_t periodic_timer;
    ESP_ERROR_CHECK(esp_timer_create(&periodic_timer_args, &periodic_timer));
    ESP_ERROR_CHECK(esp_timer_start_periodic(periodic_timer, LV_TICK_PERIOD_MS*1000));

    /* Create the demo application */
    //create_demo_application();
    //iGuiInitFlag = 1;
   // lv_demo_keypad_encoder();
    //lv_ex_msgbox_2();

     gui_Demo_init();
    /*Run the demo*/
    // lv_demo_widgets();
     gui_startUp_win_create(lv_scr_act());
    //UI_Init();//基础UI渲染函数

    while (1)
    {
        /* Delay 1 tick (assumes FreeRTOS tick is 10ms */
        vTaskDelay(10);//10ms

        /* Try to take the semaphore, call lvgl related function on success */
        if (pdTRUE == xSemaphoreTake(xGuiSemaphore, portMAX_DELAY))
        {
            lv_task_handler();
            xSemaphoreGive(xGuiSemaphore);


        if( isWinSwitch == 0 && (imgrRunCnt<45) ){//gif 粗略计时 待添加计算Gif完成的方法
            imgrRunCnt++;
        }
        else {
            if(isWinSwitch == 0){
                isWinSwitch = 1;
                imgrRunCnt = 0;
            }
           
            if(isFirstWin == 0){
                isFirstWin = 1;
               // gui_wifi_win_dele();
                lv_obj_t* NewScreen = lv_obj_create(NULL);
                lv_obj_add_event_cb(NewScreen, drag_event_handler, LV_EVENT_PRESSING, NULL);
                lv_obj_add_event_cb(NewScreen, drag_event_handler, LV_EVENT_LONG_PRESSED, NULL);
                currWinCreate[currWin](NewScreen);
                lv_scr_load_anim(NewScreen, load_right_left, 500, 200, true);

            }
            else currWinRun[currWin]();

        //    // 待添加滑动切换
        //     if(imgrRunCnt++ >30){
        //        imgrRunCnt = 0;
        //        if(++currWin >= CURR_WIN_NUM){
        //            currWin = 0;
        //        }
        //        isFirstWin = 0;
        //     }
        }

        }


    }
    /* A task should NEVER return */
    free(buf1);
    vTaskDelete(NULL);
}

